]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
windowManager: Use an off-screen buffer for window dimming
authorJasper St. Pierre <jstpierre@mecheye.net>
Sat, 17 Sep 2011 07:06:00 +0000 (03:06 -0400)
committerJasper St. Pierre <jstpierre@mecheye.net>
Mon, 19 Sep 2011 16:39:41 +0000 (12:39 -0400)
The way the window dimmer shader is applied will cause rendering errors with
the rounded corners, invisible borders or shaped textures since it doesn't deal
well with the multitexturing used by the MetaShapedTexture. Use an off-screen
buffer to flatten the texture before being applied.

https://bugzilla.gnome.org/show_bug.cgi?id=659302

data/shaders/dim-window.glsl
js/ui/windowManager.js
src/shell-util.c
src/shell-util.h

index 935c8e239e2cdaf0feb999b1b2b0b772f69f57e6..2c95022efd785d9d489c89e46cb6ff6bf12794c8 100644 (file)
@@ -1,5 +1,5 @@
 #version 110
-uniform sampler2D sampler0;
+uniform sampler2D tex;
 uniform float fraction;
 uniform float height;
 const float c = -0.2;
@@ -12,15 +12,17 @@ mat4 contrast = mat4 (1.0 + c, 0.0, 0.0, 0.0,
 vec4 off = vec4(0.633, 0.633, 0.633, 0);
 void main()
 {
-  vec4 color = texture2D(sampler0, gl_TexCoord[0].st);
-  float y = height * gl_TexCoord[0][1];
+  vec4 color = texture2D(tex, cogl_tex_coord_in[0].xy);
+  float y = height * cogl_tex_coord_in[0].y;
 
   // To reduce contrast, blend with a mid gray
-  gl_FragColor = color * contrast - off * c;
+  cogl_color_out = color * contrast - off * c;
 
   // We only fully dim at a distance of BORDER_MAX_HEIGHT from the edge and
   // when the fraction is 1.0. For other locations and fractions we linearly
   // interpolate back to the original undimmed color.
-  gl_FragColor = color + (gl_FragColor - color) * min(y / border_max_height, 1.0);
-  gl_FragColor = color + (gl_FragColor - color) * fraction;
+  cogl_color_out = color + (cogl_color_out - color) * min(y / border_max_height, 1.0);
+  cogl_color_out = color + (cogl_color_out - color) * fraction;
+
+  cogl_color_out *= color.a;
 }
index 16756ad1f2c7f90c77b378334de70be1765756a6..48276fe08ff9a538364ddd478f1c7ebc99a2debd 100644 (file)
@@ -19,22 +19,9 @@ const UNDIM_TIME = 0.250;
 
 var dimShader = undefined;
 
-function getDimShader() {
-    if (dimShader === null)
-        return null;
-    if (!dimShader) {
-        let source = Shell.get_file_contents_utf8_sync(global.datadir + '/shaders/dim-window.glsl');
-        try {
-            let shader = new Clutter.Shader();
-            shader.set_fragment_source(source, -1);
-            shader.compile();
-
-            dimShader = shader;
-        } catch (e) {
-            log(e.message);
-            dimShader = null;
-        }
-    }
+function getDimShaderSource() {
+    if (!dimShader)
+        dimShader = Shell.get_file_contents_utf8_sync(global.datadir + '/shaders/dim-window.glsl');
     return dimShader;
 }
 
@@ -44,22 +31,29 @@ function WindowDimmer(actor) {
 
 WindowDimmer.prototype = {
     _init: function(actor) {
+        this.effect = new Clutter.ShaderEffect({ shader_type: Clutter.ShaderType.FRAGMENT_SHADER });
+        this.effect.set_shader_source(getDimShaderSource());
+
         this.actor = actor;
     },
 
     set dimFraction(fraction) {
         this._dimFraction = fraction;
-        let shader = getDimShader();
-        if (!Meta.prefs_get_attach_modal_dialogs() || !shader) {
-            this.actor.set_shader(null);
+        if (!Meta.prefs_get_attach_modal_dialogs()) {
+            this.effect.enabled = false;
             return;
         }
+
         if (fraction > 0.01) {
-            this.actor.set_shader(shader);
-            this.actor.set_shader_param_float('height', this.actor.get_height());
-            this.actor.set_shader_param_float('fraction', fraction);
-        } else
-            this.actor.set_shader(null);
+            Shell.shader_effect_set_double_uniform(this.effect, 'height', this.actor.get_height());
+            Shell.shader_effect_set_double_uniform(this.effect, 'fraction', fraction);
+
+            if (!this.effect.actor)
+                this.actor.add_effect(this.effect);
+        } else {
+            if (this.effect.actor)
+                this.actor.remove_effect(this.effect);
+        }
     },
 
     get dimFraction() {
index d371861abd8aaccfed308e9481b43c90a3c69848..a06f99a54ac362834da0d91776faf6da1656ad77 100644 (file)
@@ -850,3 +850,31 @@ shell_parse_search_provider (const char    *data,
 
   return FALSE;
 }
+
+/**
+ * shell_shader_effect_set_double_uniform:
+ * @effect: The #ClutterShaderEffect
+ * @name: The name of the uniform
+ * @value: The value to set it to.
+ *
+ * Set a double uniform on a ClutterShaderEffect.
+ *
+ * The problem here is that JavaScript doesn't have more than
+ * one number type, and gjs tries to automatically guess what
+ * type we want to set a GValue to. If the number is "1.0" or
+ * something, it will use an integer, which will cause errors
+ * in GLSL.
+ */
+void
+shell_shader_effect_set_double_uniform (ClutterShaderEffect *effect,
+                                        const gchar         *name,
+                                        gdouble             value)
+{
+  GValue gvalue = G_VALUE_INIT;
+  g_value_init (&gvalue, G_TYPE_DOUBLE);
+  g_value_set_double (&gvalue, value);
+
+  clutter_shader_effect_set_uniform_value (effect,
+                                           name,
+                                           &gvalue);
+}
index 7ff08917b2b7bbf694ae0c848d8c3e37310e87cb..c0d45671eab178b34f29eb14148ee3a990193cd3 100644 (file)
@@ -50,6 +50,10 @@ gboolean shell_parse_search_provider           (const char       *data,
                                                 char            **icon_data_uri,
                                                 GError          **error);
 
+void shell_shader_effect_set_double_uniform (ClutterShaderEffect *effect,
+                                             const gchar         *name,
+                                             gdouble             value);
+
 G_END_DECLS
 
 #endif /* __SHELL_UTIL_H__ */